package com.shu.util;

import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.joda.time.Period;
import org.joda.time.PeriodType;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Date;

/**
 * 时间工具类
 */
public class JodaTimeUtil {
    /**
     * 一天的毫秒数
     */
    public static final long MILLION_SECONDS_OF_DAY = 86400000;
    /**
     * 一小时的数
     */
    public static final long MILLION_SECONDS_OF_HOUR = 3600000;
    /**
     * 一分钟的毫秒数
     */
    public static final long MILLION_SECONDS_OF_MINUTE = 60000;
    /**
     * 日期格式化格式：yyyy
     */
    public static final String FORMAT_YEAR = "yyyy";
    /**
     * 日期格式化格式：yyyyMMdd
     */
    public static final String FORMAT_DATE_STR_NO_SEP = "yyyyMMdd";
    /**
     * 日期格式化格式：yyyy-MM-dd
     */
    public static final String FORMAT_DATE_STR = "yyyy-MM-dd";
    /**
     * 日期格式化格式：yyyy-MM
     */
    public static final String FORMAT_YEAR_MONTH = "yyyy-MM";
    /**
     * 日期格式化格式：yyyyMM
     */
    public static final String FORMAT_YEAR_MONTH_1 = "yyyyMM";
    /**
     * 时间格式化格式：yyyy-MM-dd HH:mm
     */
    public static final String FORMAT_DATE_STR_ONE = "yyyy-MM-dd HH:mm";
    /**
     * 时间格式化格式：显示秒
     */
    public static final String FORMAT_DATE_STR_SECOND = "yyyy-MM-dd HH:mm:ss";
    /**
     * 年月日时分秒毫秒(无下划线) yyyyMMddHHmmssSSS
     */
    public static final String FORMAT_DATE_STR_LONG = "yyyyMMddHHmmssSSS";
    /**
     * 年月日时分秒,以横线分隔，类似于文件命名形式
     */
    public static final String FORMAT_DATE_STR_SECOND_FILE_NAME = "yyyy-MM-dd-HH-mm-ss";

    public static final DateTimeFormatter simple_str = DateTimeFormat.forPattern(FORMAT_DATE_STR);

    /**
     * 获取当前时间
     *
     * @return timestamp
     */
    public static Date getCurrentDate() {
        DateTime dateTime = new DateTime();
        Timestamp timestamp = new Timestamp(dateTime.getMillis());
        return timestamp;
    }

    public static Date getSecondDayZeroTime(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DAY_OF_YEAR, 1);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.MILLISECOND, 0);

        return cal.getTime();
    }

    /**
     * 获取当前时间
     *
     * @return timestamp
     */
    public static Timestamp getCurrentTime() {
        DateTime dateTime = new DateTime();
        Timestamp timestamp = new Timestamp(dateTime.getMillis());
        return timestamp;
    }

    /**
     * 获取当前日期
     *
     * @param fmt 默认为 yyyy-MM-dd
     * @return yyyy-MM-dd
     */
    public static String getDate(String fmt) {
        DateTimeFormatter dtf = null;
        if (StringUtils.isBlank(fmt)) {
            dtf = DateTimeFormat.forPattern(FORMAT_DATE_STR);
        } else {
            dtf = DateTimeFormat.forPattern(fmt);
        }
        return new DateTime().toString(dtf);
    }

    /**
     * 返回时间 - yyyy-MM-dd HH:mm:ss
     * @return
     */
    public static String getDateTime(){
        return new DateTime().toString(FORMAT_DATE_STR_SECOND);
    }

    /**
     * 日期格式化
     *
     * @param fmt 默认为 yyyy-MM-dd
     * @return yyyy-MM-dd
     */
    public static String getDate(Date date, String fmt) {
        DateTimeFormatter dtf = null;
        if (StringUtils.isBlank(fmt)) {
            dtf = DateTimeFormat.forPattern(FORMAT_DATE_STR);
        } else {
            dtf = DateTimeFormat.forPattern(fmt);
        }
        return new DateTime(date).toString(dtf);
    }

    /**
     * 获取 1970年1月1日00:00:00 GMT开始到现在所表示的毫秒数
     *
     * @return
     */
    public static Long getCurrentMillis() {
        DateTime dateTime = new DateTime();
        return dateTime.getMillis();
    }

    /**
     * @param date 格式"yyyy-MM-dd"
     * @return
     */
    public static Date parse(String date) {
        return DateTime.parse(date).toDate();
    }

    public static Date parse(String date, String pattern) {
        DateTimeFormatter dtf = DateTimeFormat.forPattern(pattern);
        return DateTime.parse(date, dtf).toDate();
    }

    public static Timestamp parseTimestamp(String date) {
        Date datetime = DateTime.parse(date).toDate();
        Timestamp timestamp = new Timestamp(datetime.getTime());
        return timestamp;
    }

    /**
     * 默认的格式
     *
     * @param date
     * @return 返回默认格式"yyyy-MM-dd"的字符串
     */
    public static String format(Date date) {
        DateTime dateTime = new DateTime(date);
        return dateTime.toString(simple_str);
    }

    /**
     * 默认的格式
     *
     * @param date
     * @return 返回默认格式"yyyy-MM-dd"的字符串
     */
    public static String format(String date, String format) {
        if (StringUtils.isEmpty(date)) {
            return "";
        }
        DateTime dateTime = new DateTime(date);
        return dateTime.toString(simple_str);
    }

    /**
     * 默认的格式
     *
     * @param dateTime
     * @return 返回默认格式"yyyy-MM-dd"的字符串
     */
    public static String format(DateTime dateTime) {
        return dateTime.toString(simple_str);
    }

    /**
     * @param date   当前时间
     * @param format 格式
     * @return
     */
    public static String format(Date date, String format) {
        DateTime dateTime = new DateTime(date);
        DateTimeFormatter dtf = DateTimeFormat.forPattern(format);
        return dateTime.toString(dtf);
    }

    /**
     * 增加天数
     *
     * @param date yyyy-MM-dd"的字符串
     * @param i
     * @return yyyy-MM-dd"的字符串
     */
    public static String addDay(String date, int i) {
        if (i == 0)
            return date;
        DateTime dateTime = DateTime.parse(date);
        return dateTime.plusDays(i).toString(simple_str);
    }

    /**
     * 增加天数
     *
     * @param date
     * @param i
     * @param format 格式
     * @return
     */
    public static String addDay(String date, int i, String format) {
        if (i == 0)
            return date;
        DateTimeFormatter dtf = DateTimeFormat.forPattern(format);
        DateTime dateTime = DateTime.parse(date);
        return dateTime.plusDays(i).toString(dtf);
    }


    /**
     * 增加天数
     *
     * @param date
     * @param i
     * @return
     */
    public static Date addDays(Date date, int i) {
        DateTimeFormatter dtf = DateTimeFormat.forPattern(FORMAT_DATE_STR);
        DateTime dateTime = new DateTime(date);
        if (i == 0)
            return dateTime.toDate();
        return dateTime.plusDays(i).toDate();
    }


    /**
     * 减去天数
     *
     * @param date
     * @param i
     * @return
     */
    public static Date minusDays(Date date, int i) {
        DateTimeFormatter dtf = DateTimeFormat.forPattern(FORMAT_DATE_STR);
        DateTime dateTime = new DateTime(date);
        if (i == 0)
            return dateTime.toDate();
        return dateTime.minusDays(i).toDate();
    }


    /**
     * 得到两个日期之间相差的年数
     *
     * @param startTime
     * @param endTime
     * @param formatter
     * @return
     */
    public static int getDifferYear(String startTime, String endTime, String formatter) {
        DateTimeFormatter dtf = DateTimeFormat.forPattern(formatter);
        DateTime startTime_tmp = DateTime.parse(startTime, dtf);
        DateTime endTime_tmp = DateTime.parse(endTime, dtf);
        Period p = new Period(startTime_tmp, endTime_tmp, PeriodType.years());
        int days = p.getYears();
        return Math.abs(days);
    }

    /**
     * 得到两个日期之间相差的天数,返回值 = big - small
     *
     * @param big
     * @param small
     * @return
     */
    public static int getDifferDay(Date big, Date small) {
        String b = format(big);
        String s = format(small);
        return getDifferDay(b, s);
    }

    /**
     * 得到两个日期之间相差的月数 ,返回值 = big - small
     *
     * @param big
     * @param small
     * @return
     */
    public static int getDifferMonth(Date big, Date small) {
        DateTime big1 = new DateTime(big);
        DateTime small1 = new DateTime(small);
        Period p = new Period(small1, big1, PeriodType.months());
        return p.getMonths();
    }

    /**
     * 得到两个日期之间相差的天数,返回值 = big - small
     *
     * @param big
     * @param small
     * @return
     */
    public static int getDifferDay(String big, String small) {
        DateTime small1 = DateTime.parse(small);
        DateTime big1 = DateTime.parse(big);
        Period p = new Period(small1, big1, PeriodType.days());
        return p.getDays();
    }


    /**
     * 得到两个日期之间相差的分钟数
     *
     * @param startTime
     * @param endTime
     * @return
     */
    public static int getDifferMinutes(Date startTime, Date endTime) {
        DateTime startTime_tmp = new DateTime(startTime);
        DateTime endTime_tmp = new DateTime(endTime);
        Period p = new Period(startTime_tmp, endTime_tmp, PeriodType.minutes());
        int mins = p.getMinutes();
        return Math.abs(mins);
    }


    /**
     * 得到两个时间之间相差的秒差数
     *
     * @param startTime
     * @param endTime
     * @return
     */
    public static int getDifferSeconds(String startTime, String endTime) {
        DateTimeFormatter dtf = DateTimeFormat.forPattern(JodaTimeUtil.FORMAT_DATE_STR_SECOND);
        DateTime startTime_tmp = DateTime.parse(startTime, dtf);
        DateTime endTime_tmp = DateTime.parse(endTime, dtf);
        Period p = new Period(startTime_tmp, endTime_tmp, PeriodType.seconds());
        int seconds = p.getSeconds();
        return Math.abs(seconds);
    }


    /**
     * 得到两个时间之间相差的秒差数，相对值
     *
     * @param startTime
     * @param endTime
     * @return
     */
    public static int getDifferSeconds(DateTime startTime, DateTime endTime) {
        Period p = new Period(startTime, endTime, PeriodType.seconds());
        int seconds = p.getSeconds();
        return seconds;
    }

    /**
     * 判断当前天是星期几
     *
     * @param date
     * @return 数字
     */
    public static int dayOfWeek(String date) {
        DateTime dateTime = DateTime.parse(date);
        return dateTime.dayOfWeek().get();
    }

    /**
     * 比较时间大小
     *
     * @param date1
     * @param date2
     * @return date1 < date2 true
     */
    public static boolean compareDate(String date1, String date2) {
        DateTime dateTime1 = new DateTime(date1);
        long a = dateTime1.getMillis();
        DateTime dateTime2 = new DateTime(date2);
        long b = dateTime2.getMillis();
        return a < b ? true : false;
    }

    /**
     * 比较时间大小
     *
     * @param date1
     * @param date2
     * @return date1 < date2 true
     */
    public static boolean compareDate(Date date1, Date date2) {
        DateTime dateTime1 = new DateTime(date1);
        long a = dateTime1.getMillis();
        DateTime dateTime2 = new DateTime(date2);
        long b = dateTime2.getMillis();
        return a < b ? true : false;
    }

    /**
     * 比较时间大小
     *
     * @param date1
     * @param date2
     * @return date1 > date2 返回1
     * date1 < date2 返回-1
     * date1 = date2 返回0
     */
    public static int compareDates(String date1, String date2) {
        DateTime dateTime1 = new DateTime(date1);
        long a = dateTime1.getMillis();
        DateTime dateTime2 = new DateTime(date2);
        long b = dateTime2.getMillis();
        if (a > b) {
            return 1;
        } else if (a < b) {
            return -1;
        } else {
            return 0;
        }
    }

    /**
     * 比较两个时间， 取较大的时间
     *
     * @param date1
     * @param date2
     * @return
     */
    public static String compareOfMax(String date1, String date2) {
        DateTime dateTime1 = new DateTime(date1);
        long a = dateTime1.getMillis();
        DateTime dateTime2 = new DateTime(date2);
        long b = dateTime2.getMillis();
        return a >= b ? date1 : date2;
    }

    /**
     * 比较两个时间，取较小的时间
     *
     * @param date1
     * @param date2
     * @return
     */
    public static String compareOfMin(String date1, String date2) {
        DateTime dateTime1 = new DateTime(date1);
        long a = dateTime1.getMillis();
        DateTime dateTime2 = new DateTime(date2);
        long b = dateTime2.getMillis();
        return a >= b ? date2 : date1;
    }

    /**
     * @param date eg: 2015-05-06 -> 2015-05-06 23:59:59
     */
    public static String add23Hours(String date) {
        if (StringUtils.isNotEmpty(date)) {
            String day = addDay(date, 1);
            DateTime dateTime = DateTime.parse(day);
            DateTime time = dateTime.plusSeconds(-1);
            return time.toString(FORMAT_DATE_STR_SECOND);

        }
        return null;
    }

    /**
     * 判断两个时间是否属于同一个月
     *
     * @param date1
     * @param date2
     * @return
     */
    public static boolean judgeOfOneMonth(String date1, String date2) {
        DateTime dt1 = DateTime.parse(date1);
        DateTime dt2 = DateTime.parse(date2);
        return dt1.year().get() == dt2.year().get() && dt1.monthOfYear().get() == dt2.monthOfYear().get();
    }

    /**
     * 获取本月第一天时间类型
     *
     * @param date
     * @return
     */
    public static Timestamp getFirstDayOfMontht(String date) {
        DateTime dt = DateTime.parse(date);
        DateTime dateTime = dt.dayOfMonth().withMinimumValue();
        return parseTimestamp(format(dateTime));
    }

    /**
     * 获取本月第一天
     *
     * @param date
     * @return
     */
    public static String getFirstDayOfMonth(String date) {
        DateTime dt = DateTime.parse(date);
        DateTime dateTime = dt.dayOfMonth().withMinimumValue();
        return format(dateTime);
    }

    /**
     * 获取本月最后一天
     *
     * @param date
     * @return
     */
    public static String getLastDayOfMonth(String date) {
        DateTime dt = DateTime.parse(date);
        DateTime dateTime = dt.dayOfMonth().withMaximumValue();
        return format(dateTime);
    }

    /**
     * 增加月数
     *
     * @param date
     * @param i
     * @param format 格式
     * @return
     */
    public static String addMonth(String date, int i, String format) {
        if (i == 0)
            return date;
        DateTimeFormatter dtf = DateTimeFormat.forPattern(format);
        DateTime dateTime = DateTime.parse(date);
        return dateTime.plusMonths(i).toString(dtf);
    }

    /**
     * 增加月数
     *
     * @param date
     * @param i
     * @param format 格式
     * @return
     */
    public static String addMonth(Date date, int i, String format) {
        DateTimeFormatter dtf = DateTimeFormat.forPattern(format);
        DateTime dateTime = new DateTime(date);
        if (i == 0)
            return dateTime.toString(dtf);
        return dateTime.plusMonths(i).toString(dtf);
    }

    /**
     * 增加月数
     *
     * @param date
     * @param i
     * @return
     */
    public static Date addMonth(Date date, int i) {
//        DateTimeFormatter dtf = DateTimeFormat.forPattern(FORMAT_DATE_STR);
        DateTime dateTime = new DateTime(date);
        if (i == 0)
            return dateTime.toDate();
        return dateTime.plusMonths(i).toDate();
    }


    /**
     * 周岁
     *
     * @param birth
     * @return
     */
    public static Integer getAgeFromBirth(String birth, String format) {
        if (StringUtils.isEmpty(format)) {
            format = FORMAT_DATE_STR;
        }
        if (birth == null || "".equals(birth) || "null".equals(birth)) {
            return null;
        }
        DateTimeFormatter formater = DateTimeFormat.forPattern(format);
        //时间解析
        LocalDate birthday = DateTime.parse(birth, formater).toLocalDate();
        LocalDate now = new LocalDate();
        Period period = new Period(birthday, now, PeriodType.yearMonthDay());
        return period.getYears();
    }

    /**
     * 周岁
     *
     * @param birth
     * @return
     */
    public static Integer getAgeFromBirth(Date birth, String format) {
        if (StringUtils.isEmpty(format)) {
            format = FORMAT_DATE_STR;
        }
        if (birth == null) {
            return null;
        }
        DateTimeFormatter formater = DateTimeFormat.forPattern(format);
        //时间解析
        LocalDate birthday = new DateTime(birth).toLocalDate();
        LocalDate now = new LocalDate();
        Period period = new Period(birthday, now, PeriodType.yearMonthDay());
        return period.getYears();
    }

    public static int getTime(Date begin, Date end) {
        long between = (end.getTime() - begin.getTime()) / 1000;//除以1000是为了转换成秒
        long min = (between / 60);
        return (int) min;
    }

    /**
     * 是否过期
     *
     * @param date
     * @param format
     * @return true, false
     */
    public static boolean isExpired(String date, String format) {
        DateTimeFormatter dtf = DateTimeFormat.forPattern(format);
        DateTime dateTime = dtf.parseDateTime(date);
        DateTime now = new DateTime(new Date());
        if (now.getMillis() >= dateTime.getMillis()) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 增加分钟数后是否过期
     *
     * @param date
     * @param addMinites 增加的分钟数
     * @param format
     * @return true, false
     */
    public static boolean isExpired(String date, Integer addMinites, String format) {
        DateTimeFormatter dtf = DateTimeFormat.forPattern(format);
        DateTime dateTime = dtf.parseDateTime(date).plusMinutes(addMinites);//增加分钟数
        DateTime now = dtf.parseDateTime(new DateTime(new Date()).toString(format));
        if (now.getMillis() >= dateTime.getMillis()) {
            return true;
        } else {
            return false;
        }
    }

    //获取本周日期范围
    public static String[] getCurrentWeekRange() {
        DateTime now = DateTime.now();
        String[] range = new String[2];
        range[0] = format(now.dayOfWeek().withMinimumValue());
        range[1] = format(now.dayOfWeek().withMaximumValue());
        return range;
    }

    //获取本月日期范围
    public static String[] getCurrentMonthRange() {
        DateTime now = DateTime.now();
        String[] range = new String[2];
        range[0] = format(now.dayOfMonth().withMinimumValue());
        range[1] = format(now.dayOfMonth().withMaximumValue());
        return range;
    }

    /**
     * @param date 日期
     * @param i    增加/减少 i 个月
     * @param fmt  返回值的日期格式
     * @return
     */
    public static String getMonth(Date date, int i, String fmt) {
        DateTimeFormatter dtf = DateTimeFormat.forPattern(fmt);
        DateTime dateTime = new DateTime(date);
        if (i == 0)
            return dateTime.toString(dtf);
        return dateTime.plusMonths(i).toString(dtf);
    }

    /**
     * @param date 日期
     * @param i    增加/减少 i 个月
     * @param fmt  返回值的日期格式
     * @return
     */
    public static String getMonth(String date, int i, String fmt) {
        DateTimeFormatter dtf = DateTimeFormat.forPattern(fmt);
        DateTime dateTime = dtf.parseDateTime(date);
        if (i == 0)
            return dateTime.toString(dtf);
        return dateTime.plusMonths(i).toString(dtf);
    }

    public static String dateFmt(String date, String oldFmt, String newFmt) {
        DateTimeFormatter dtf = DateTimeFormat.forPattern(oldFmt);
        return dtf.parseDateTime(date).toString(newFmt);
    }

    public static void main(String[] args) {
        //System.out.printf(addDays(new Date(),10).toString());
        //System.out.println(getDifferDay(new Date(),JodaTimeUtil.addDays(new Date(),10)));
//        System.out.println(getDifferMinutes(new Date(),new DateTime(new Date()).plusMinutes(10).toDate()));
//        System.out.println(dayOfWeek("2018-09-10"));
//        System.out.println(isExpired("2018-09-10 15:49","yyyy-MM-dd HH:mm"));
//        System.out.println(isExpired("2018-06-02 15:54",-30,"yyyy-MM-dd HH:mm"));
//        System.out.println(isExpired("2018-06-02 15:55",-30,"yyyy-MM-dd HH:mm"));
//        System.out.println(getDate());
//
//        System.out.println(getCurrentMonthRange()[0]+" "+getCurrentMonthRange()[1]);
//        System.out.println(getCurrentWeekRange()[0]+" "+getCurrentWeekRange()[1]);
//        System.out.println(JodaTimeUtil.getAgeFromBirth(new Date(),JodaTimeUtil.FORMAT_DATE_STR));

        int month = JodaTimeUtil.getDifferMonth(new Date(), new DateTime(new Date()).plusDays(-3).toDate());
        int day = JodaTimeUtil.getDifferDay(new Date(), new DateTime(new Date()).plusDays(-3).toDate());
        int seconds = JodaTimeUtil.getDifferSeconds(new DateTime(), new DateTime(new Date()).plusDays(3));
        System.out.println(month);
        System.out.println(day);
        System.out.println(seconds);

    }

}